/*
 ------------------------------------------------------------------------------
 Copyright (C) 1996-2001 Id Software, Inc.

 This file is part of the Quake source code.

 The Quake source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quake source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quake source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// sv_local.h - local header to all server files
//


#ifndef __SV_LOCAL_H__
#define __SV_LOCAL_H__


#include "../common/common.h"
#include "../game/server/sg_public.h"
#include "../collision/cm_public.h"


/*
 ==============================================================================

 GLOBALS

 ==============================================================================
*/

// MAX_CHALLENGES is made large to prevent denial of service attacks that could
// cycle all of them out before legitimate users connected
#define	MAX_CHALLENGES					1024

#define HEARTBEAT_TIMEOUT				300000

// Client states
enum clientState_t {
	CS_FREE,									// Can be reused for a new connection
	CS_ZOMBIE,									// Client has been disconnected, but don't reuse connection yet
	CS_CONNECTED,								// Has been assigned to a client_t, but no server state yet
	CS_PRIMED,									// Server state has been sent, but client hasn't sent a user command
	CS_ACTIVE									// Client is fully in game
};

struct clientPacket_t {
	int						timeSent;			// Time when packet was sent
	int						timeAcked;			// Time when packet was acknowledged
};

struct client_t {
	clientState_t			state;				// Client status

	int						clientNum;

	int						serverId;

	bool					pureAuthentic;		// If false, don't allow the client into the game

	bool					rateDelayed;		// If true, nextPacketTime was set based on rate instead of GAME_FRAMEMSEC

	int						serverStateMessage;	// To detect if a server state needs to be (re)sent

	int						gameStateMessage;	// To detect if a game state needs to be (re)sent
	int						gameStateOffset;	// Requested game state offset

	int						deltaMessage;		// Requested delta message sequence

	int						messageAcknowledge;	// Acknowledged message sequence

	userCmd_t				lastUserCmd;		// Last user command executed

	// User information
	char					userInfo[MAX_STRING_LENGTH];

	char					playerName[MAX_PLAYER_NAME_LENGTH];
	int						voiceChat;			// 1 = receive, 2 = send, 3 = receive and send
	int						rate;				// Bytes per second
	int						ping;

	// Packets information
	clientPacket_t			packets[PACKET_BACKUP];
	int						nextPacketTime;		// Send another packet when svs.time >= nextPacketTime

	// Connection information
	netChan_t				netChan;

	int						lastConnectTime;	// For reconnection requests
	int						lastReceivedTime;	// For time-outs

	int						timeOutCount;		// It requires several frames in a time-out condition to disconnect

	// Reliable commands to send to the client
	int						reliableCommandSequence;
	int						reliableCommandAcknowledge;
	char					reliableCommandList[MAX_RELIABLE_COMMANDS][MAX_STRING_LENGTH];

	// Reliable commands received from the client
	int						clientCommandSequence;
	int						clientCommandTime;

	// File download information
	ulong					downloadChecksum;
};

struct challenge_t {
	netAdr_t				address;

	int						challenge;
	int						time;
};

struct serverActive_t {
	int						serverId;

	int						timeResidual;		// When >= GAME_FRAMEMSEC, run the game simulation

	// The multicast buffer is used to send a message to a set of 
	// clients
	msg_t					multicast;
	byte					multicastBuffer[MAX_MSG_SIZE];
};

struct serverStatic_t {
	bool					initialized;		// Sever initialization has completed

	int						time;				// Will be strictly increasing across level changes
	
	glqRandom				random;

	client_t *				clients;

	// Master server information
	bool					masterResolved;
	netAdr_t				masterAddress;
	int						masterHeartbeatTime;

	// Challenges to prevent invalid IPs from connecting
	challenge_t				challenges[MAX_CHALLENGES];

	// Game module handle
	void *					gameLibHandle;
};

extern serverActive_t		sv;
extern serverStatic_t		svs;

extern cvar_t *				sv_padPackets;
extern cvar_t *				sv_showRate;
extern cvar_t *				sv_serverId;
extern cvar_t *				sv_map;
extern cvar_t *				sv_pure;
extern cvar_t *				sv_allowCheats;
extern cvar_t *				sv_voiceChat;
extern cvar_t *				sv_numClients;
extern cvar_t *				sv_maxClients;
extern cvar_t *				sv_minPing;
extern cvar_t *				sv_maxPing;
extern cvar_t *				sv_maxRate;
extern cvar_t *				sv_password;
extern cvar_t *				sv_needPassword;
extern cvar_t *				sv_floodProtect;
extern cvar_t *				sv_lanServer;
extern cvar_t *				sv_clientTimeOut;
extern cvar_t *				sv_zombieTimeOut;
extern cvar_t *				sv_reconnectLimit;

void			SV_SpawnServer (const char *levelName, bool allowCheats);

void			SV_AddReliableCommand (client_t *client, const char *fmt, ...);
void			SV_BroadcastReliableCommand (const char *fmt, ...);

void			SV_DropClient (client_t *client, const char *reason);
void			SV_UserInfoChanged (client_t *client);

void			SV_ParseClientMessage (client_t *client, msg_t *msg);

void			SV_ReadPackets (bool dump);

void			SV_SendPacketToClient (client_t *client, bool forceSend);
void			SV_SendClientPackets ();

void			SV_Map_f ();
void			SV_DevMap_f ();
void			SV_LoadGame_f ();
void			SV_SaveGame_f ();

/*
 ==============================================================================

 INTERFACE TO GAME MODULE

 ==============================================================================
*/

extern glqSGame_t *			glqSGame;

void			SG_Init ();
void			SG_Shutdown ();


#endif	// __SV_LOCAL_H__